/*****************************************************************************/
/*                                                                           */
/*    Domino Operation System System Specific Module                         */
/*                                                                           */
/*    Copyright (C) 2013 Laszlo Arvai                                        */
/*                                                                           */
/*    ------------------------------------------------------------------   */
/*    drvSocket - Network socket API implementation for WIN32 emulation      */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Includes
#include <winsock2.h>
#define _netSocket_NO_WRAPPERS
#include <netSocket.h>
#include <stdio.h>
#include <stdlib.h>

///////////////////////////////////////////////////////////////////////////////
// Constants
#define O_NONBLOCK 1


///////////////////////////////////////////////////////////////////////////////
// Initialize network access
void netInitialize(void)
{
	WSADATA WsaDat;

	if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)
	{
		fprintf(stderr, "Winsock error - Winsock initialization failed\r\n");
		WSACleanup();
		exit(1);
	}

	// register cleanup function
	atexit(netCleanUp);
}

///////////////////////////////////////////////////////////////////////////////
// Cleanup network socket AIP service
void netCleanUp(void)
{
	WSACleanup();
}

///////////////////////////////////////////////////////////////////////////////
// Network process
dosBool netProcess(void)
{
	return dosTrue;
}

///////////////////////////////////////////////////////////////////////////////
// Opens socket
netSOCKET netSocketOpen( int af, int type, int protocol )
{
	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if(s != INVALID_SOCKET)
	{
		u_long iMode = O_NONBLOCK;
		ioctlsocket(s, FIONBIO, &iMode);
	}

	return s;
}

///////////////////////////////////////////////////////////////////////////////
// Closes socket
int netCloseSocket(netSOCKET s)
{
	return closesocket(s);
}

///////////////////////////////////////////////////////////////////////////////
// Bind socket
int netBind(netSOCKET s, const struct sockaddr* name, int namelen)
{
	return bind( s, name, namelen );
}

///////////////////////////////////////////////////////////////////////////////
// Connect socket
int netConnect(netSOCKET s, const struct sockaddr* name, int namelen)
{
	return connect( s, name, namelen );
}


///////////////////////////////////////////////////////////////////////////////
// Checks is socket is already connected
dosBool netIsConnected(netSOCKET s)
{
	fd_set fdset;
	int retval;
	struct timeval tv;

	tv.tv_sec = 0;

	FD_ZERO(&fdset);
	FD_SET(s, &fdset);

	retval = select(s, NULL, &fdset, NULL, &tv);

	return (retval == 1);
}

///////////////////////////////////////////////////////////////////////////////
// Check if socket TX is ready
dosBool netIsTXReady(netSOCKET s)
{
	fd_set fdset;
	int retval;
	struct timeval tv;

	tv.tv_sec = 0;

	FD_ZERO(&fdset);
	FD_SET(s, &fdset);

	retval = select(s, NULL, &fdset, NULL, &tv);

	return (retval == 1);
}

///////////////////////////////////////////////////////////////////////////////
// Send data
int netSend( netSOCKET s, const char* buf, int len, int flags )
{
	return send(s, buf, len, flags);
}

///////////////////////////////////////////////////////////////////////////////
// Receive data
int netRecvfrom( netSOCKET s, char* buf, int len, int flags, struct sockaddr* from, socklen_t* fromlen )
{
	return recvfrom(s, buf, len, flags, from, fromlen);
}

///////////////////////////////////////////////////////////////////////////////
// Receive data
int netReceive( netSOCKET s, char* buf, int len, int flags)
{
	return recv(s, buf, len, flags);
}
